Note: Open Rproj first, then script. To easily use relative
paths, click the down button next to knit and then click “Knit Directory
–> Project Directory”. This should make loading and saving files much
easier.
1. Load packages and input data
Load packages
library(edgeR, quietly = TRUE) #edgeR-v3.30.3
library(vegan, quietly = TRUE)
library(Dune, quietly = TRUE)
library(ggplot2, quietly = TRUE) #ggplot2-v3.3.5
library(tidyverse, quietly = TRUE) #tidyverse-v1.3.1
library(Rmisc, quietly = TRUE)
library(mixOmics, quietly = TRUE)
#library(ggridges)
#library(hrbrthemes)
#library(viridis)
Load the input file containing the treatment information
#treatment information
treatmentinfo <- read.csv("Sample_Info/samples_Pacuta.annotations.txt", header = TRUE, sep = "\t", fileEncoding="UTF-8-BOM") #read in file
top3groups <- c("Group2", "Group3", "Group6")
treatmentinfo <- filter(treatmentinfo, group%in%top3groups)
table(treatmentinfo$group)
Group2 Group3 Group6
34 24 27
Load the input file containing the gene count matrix
#gene count matrix
gcount <- as.data.frame(read_delim("Genome_Info/Pocillopora_acuta_KBHIv2.gentrome.fa.gz.salmon.numreads.matrix", delim = "\t", col_names = TRUE, show_col_types = FALSE), fileEncoding="UTF-8-BOM") #read in file
rownames(gcount) <- gcount$Name #makes "Name" the rowname
gcount <- gcount[,-c(1)] #drops the "Name" column
gcount <- round(gcount) #round
dim(gcount); head(gcount)[,1:3] #view dataset attributes
[1] 33259 119
gcount <- gcount[,treatmentinfo$sample]
Determine library size
libSize.df <- data.frame(libSize=colSums(gcount))
Make DGE object
DGEdat <- DGEList(counts=as.matrix(gcount), samples=treatmentinfo,
group=treatmentinfo$temp)
dim(DGEdat$counts)
[1] 33259 85
2. Pre-filtering
lib.sizes.cpm <- colSums(gcount)/1000000
lib.sizes.cpm <- tibble(sample=colnames(gcount), lib.size=lib.sizes.cpm)
keep <- rowSums(cpm(gcount) > 3.33) >= 2
table(keep)
keep
FALSE TRUE
12211 21048
DGEdat <- DGEdat[keep, , keep.lib.sizes=FALSE]
3. Data normalization
DGEdat <- calcNormFactors(DGEdat)
DGEdat$samples
4. Plot global gene expression
Log transform the counts matrix for the next plots
DGEdat.cpm <- DGEdat #make a copy the edgeR dataset
DGEdat.cpm$counts <- cpm(DGEdat.cpm$counts, log=TRUE, prior.count=5) #log transform the copy for the next plots
Run a principle coordinates analysis, all samples
d <- data.frame(DGEdat.cpm$samples, name = colnames(DGEdat.cpm$counts), TP_temp=paste(DGEdat.cpm$samples$timename, DGEdat.cpm$samples$temp, sep="_")) #make a dataframe containing all plotting info
#d <- filter(d, temp=="Hot")
d$timename <- factor(d$timename, levels = c("0_hour", "6_hour", "12_hour", "30_hour", "1_week", "2_week", "4_week", "6_week", "8_week", "12_week"))
ncol(DGEdat.cpm$counts[,d$sample])
[1] 85
# Partial Least Squares Analysis
mixOmic_plsda <- plsda(t(DGEdat.cpm$counts[,d$sample]), d$timename, ncomp = 85)
plotVar(mixOmic_plsda, plot = F)
plsda_plot <- biplot(mixOmic_plsda, var.axes = TRUE, cutoff = .8, ind.names = F); plsda_plot

plotIndiv(mixOmic_plsda, ind.names = F, ellipse = TRUE, legend = TRUE)

Run a principle coordinates analysis, Hot samples
d <- data.frame(DGEdat.cpm$samples, name = colnames(DGEdat.cpm$counts), TP_temp=paste(DGEdat.cpm$samples$timename, DGEdat.cpm$samples$temp, sep="_")) #make a dataframe containing all plotting info
d$timename <- factor(d$timename, levels = c("0_hour", "6_hour", "12_hour", "30_hour", "1_week", "2_week", "4_week", "6_week", "8_week", "12_week"))
d <- filter(d, temp=="Hot")
ncol(DGEdat.cpm$counts[,d$sample])
[1] 44
# Partial Least Squares Analysis
mixOmic_plsda <- plsda(t(DGEdat.cpm$counts[,d$sample]), d$TP_temp, ncomp = 44)
plotVar(mixOmic_plsda, plot = F)
plsda_plot <- biplot(mixOmic_plsda, var.axes = TRUE, cutoff = .8, ind.names = F); plsda_plot

plotIndiv(mixOmic_plsda, ind.names = F, ellipse = TRUE, legend = TRUE)

Run a principle coordinates analysis, Amb samples
d <- data.frame(DGEdat.cpm$samples, name = colnames(DGEdat.cpm$counts), TP_temp=paste(DGEdat.cpm$samples$timename, DGEdat.cpm$samples$temp, sep="_")) #make a dataframe containing all plotting info
d$timename <- factor(d$timename, levels = c("0_hour", "6_hour", "12_hour", "30_hour", "1_week", "2_week", "4_week", "6_week", "8_week", "12_week"))
d <- filter(d, temp=="Amb")
ncol(DGEdat.cpm$counts[,d$sample])
[1] 41
# Partial Least Squares Analysis
mixOmic_plsda <- plsda(t(DGEdat.cpm$counts[,d$sample]), d$TP_temp, ncomp = 41)
plotVar(mixOmic_plsda, plot = F)
plsda_plot <- biplot(mixOmic_plsda, var.axes = TRUE, cutoff = .8, ind.names = F); plsda_plot

plotIndiv(mixOmic_plsda, ind.names = F, ellipse = TRUE, legend = TRUE)

Emma script
# set working directory and load necessary packages
library(reshape2)
#library(ggbiplot)
library(broom) # devtools::install_github("tidymodels/broom")
library(cowplot)
library(ggpubr)
#library(ggfortify)
library(ggrepel)
library(gridExtra)
#library(ggforce)
# set seed
set.seed(54321)
Load datasets
d <- data.frame(DGEdat.cpm$samples, name = colnames(DGEdat.cpm$counts), TP_temp=paste(DGEdat.cpm$samples$timename, DGEdat.cpm$samples$temp, sep="_")) #make a dataframe
d$timename <- factor(d$timename, levels = c("0_hour", "6_hour", "12_hour", "30_hour", "1_week", "2_week", "4_week", "6_week", "8_week", "12_week"))
#PCA
Mcap.pca.out <- prcomp(t(DGEdat.cpm$counts[,d$sample])) #, center=FALSE, scale=FALSE) #run PCA
M.summary <- summary(Mcap.pca.out); M.summary #view results
Importance of components:
PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 PC11 PC12 PC13 PC14 PC15
Standard deviation 47.8457 39.3804 31.8471 23.44963 19.12449 16.68497 15.27388 14.09774 12.78940 11.69200 11.33499 10.95941 10.53431 10.13147 9.45036
Proportion of Variance 0.2376 0.1609 0.1053 0.05707 0.03796 0.02889 0.02421 0.02063 0.01698 0.01419 0.01333 0.01247 0.01152 0.01065 0.00927
Cumulative Proportion 0.2376 0.3985 0.5038 0.56085 0.59881 0.62770 0.65191 0.67253 0.68951 0.70370 0.71703 0.72950 0.74101 0.75166 0.76093
PC16 PC17 PC18 PC19 PC20 PC21 PC22 PC23 PC24 PC25 PC26 PC27 PC28 PC29 PC30 PC31 PC32
Standard deviation 9.07542 8.86547 8.54723 8.36652 8.11764 8.07213 7.72604 7.4751 7.33188 6.98285 6.81872 6.75749 6.59476 6.50150 6.39636 6.34873 6.27945
Proportion of Variance 0.00855 0.00816 0.00758 0.00726 0.00684 0.00676 0.00619 0.0058 0.00558 0.00506 0.00483 0.00474 0.00451 0.00439 0.00425 0.00418 0.00409
Cumulative Proportion 0.76948 0.77764 0.78522 0.79248 0.79932 0.80609 0.81228 0.8181 0.82366 0.82872 0.83354 0.83828 0.84280 0.84718 0.85143 0.85561 0.85970
PC33 PC34 PC35 PC36 PC37 PC38 PC39 PC40 PC41 PC42 PC43 PC44 PC45 PC46 PC47 PC48 PC49
Standard deviation 6.15489 6.07861 6.03575 5.97942 5.90674 5.84883 5.79111 5.76026 5.70003 5.66802 5.6388 5.61025 5.55841 5.49090 5.45282 5.42537 5.36089
Proportion of Variance 0.00393 0.00383 0.00378 0.00371 0.00362 0.00355 0.00348 0.00344 0.00337 0.00333 0.0033 0.00327 0.00321 0.00313 0.00309 0.00305 0.00298
Cumulative Proportion 0.86364 0.86747 0.87125 0.87496 0.87858 0.88213 0.88561 0.88906 0.89243 0.89576 0.8991 0.90233 0.90554 0.90866 0.91175 0.91481 0.91779
PC50 PC51 PC52 PC53 PC54 PC55 PC56 PC57 PC58 PC59 PC60 PC61 PC62 PC63 PC64 PC65 PC66
Standard deviation 5.33055 5.26422 5.23060 5.20470 5.1901 5.13711 5.12038 5.06910 5.04595 5.01429 4.99416 4.95214 4.93965 4.89052 4.84779 4.8065 4.78845
Proportion of Variance 0.00295 0.00288 0.00284 0.00281 0.0028 0.00274 0.00272 0.00267 0.00264 0.00261 0.00259 0.00255 0.00253 0.00248 0.00244 0.0024 0.00238
Cumulative Proportion 0.92074 0.92361 0.92645 0.92926 0.9321 0.93480 0.93752 0.94019 0.94283 0.94544 0.94803 0.95057 0.95310 0.95559 0.95802 0.9604 0.96280
PC67 PC68 PC69 PC70 PC71 PC72 PC73 PC74 PC75 PC76 PC77 PC78 PC79 PC80 PC81 PC82 PC83
Standard deviation 4.76581 4.74457 4.71724 4.67894 4.63921 4.58973 4.55821 4.53962 4.49122 4.47088 4.40430 4.37397 4.34636 4.2770 4.24909 4.21365 4.1665
Proportion of Variance 0.00236 0.00234 0.00231 0.00227 0.00223 0.00219 0.00216 0.00214 0.00209 0.00207 0.00201 0.00199 0.00196 0.0019 0.00187 0.00184 0.0018
Cumulative Proportion 0.96516 0.96749 0.96980 0.97208 0.97431 0.97650 0.97865 0.98079 0.98288 0.98496 0.98697 0.98896 0.99092 0.9928 0.99469 0.99653 0.9983
PC84 PC85
Standard deviation 4.00645 5.257e-14
Proportion of Variance 0.00167 0.000e+00
Cumulative Proportion 1.00000 1.000e+00
biplot(Mcap.pca.out) #plot results


Mcapitata.all <- Mcap.pca.out %>%
augment(d) %>% # add original dataset back in
group_by(timename, temp) %>%
mutate(PC5.mean = mean(.fittedPC5),
PC6.mean = mean(.fittedPC6))
mcap.Hot.segments <- Mcapitata.all %>% subset(temp == "Hot") %>%
select(timename, temp, PC5.mean, PC6.mean) %>%
gather(variable, value, -(timename:temp)) %>%
unite(group, timename, variable) %>% distinct() %>%
spread(group, value)
mcap.amb.segments <- Mcapitata.all %>% subset(temp == "Amb") %>%
select(timename, temp, PC5.mean, PC6.mean) %>%
gather(variable, value, -(timename:temp)) %>%
unite(group, timename, variable) %>% distinct() %>%
spread(group, value)

LS0tCnRpdGxlOiAiUExTLURBIG9mICpQLiBhY3V0YSogZ2VuZSBleHByZXNzaW9uIgphdXRob3I6ICJFcmluIENoaWxsZSIKZGF0ZTogIjA1LzA5LzIwMjQiCm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpybShsaXN0ID0gbHMoKSkgI2NsZWFyIGVudmlyb25tZW50CmBgYAoKKk5vdGU6IE9wZW4gUnByb2ogZmlyc3QsIHRoZW4gc2NyaXB0LiBUbyBlYXNpbHkgdXNlIHJlbGF0aXZlIHBhdGhzLCBjbGljayB0aGUgZG93biBidXR0b24gbmV4dCB0byBrbml0IGFuZCB0aGVuIGNsaWNrICJLbml0IERpcmVjdG9yeSAtLT4gUHJvamVjdCBEaXJlY3RvcnkiLiBUaGlzIHNob3VsZCBtYWtlIGxvYWRpbmcgYW5kIHNhdmluZyBmaWxlcyBtdWNoIGVhc2llci4qCgojIyAxLiBMb2FkIHBhY2thZ2VzIGFuZCBpbnB1dCBkYXRhCgpMb2FkIHBhY2thZ2VzCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGVkZ2VSLCBxdWlldGx5ID0gVFJVRSkgI2VkZ2VSLXYzLjMwLjMKbGlicmFyeSh2ZWdhbiwgcXVpZXRseSA9IFRSVUUpCmxpYnJhcnkoRHVuZSwgcXVpZXRseSA9IFRSVUUpCmxpYnJhcnkoZ2dwbG90MiwgcXVpZXRseSA9IFRSVUUpICNnZ3Bsb3QyLXYzLjMuNQpsaWJyYXJ5KHRpZHl2ZXJzZSwgcXVpZXRseSA9IFRSVUUpICN0aWR5dmVyc2UtdjEuMy4xCmxpYnJhcnkoUm1pc2MsIHF1aWV0bHkgPSBUUlVFKQpsaWJyYXJ5KG1peE9taWNzLCBxdWlldGx5ID0gVFJVRSkKI2xpYnJhcnkoZ2dyaWRnZXMpCiNsaWJyYXJ5KGhyYnJ0aGVtZXMpCiNsaWJyYXJ5KHZpcmlkaXMpCgpgYGAKCkxvYWQgdGhlIGlucHV0IGZpbGUgY29udGFpbmluZyB0aGUgdHJlYXRtZW50IGluZm9ybWF0aW9uCmBgYHtyfQojdHJlYXRtZW50IGluZm9ybWF0aW9uCnRyZWF0bWVudGluZm8gPC0gcmVhZC5jc3YoIlNhbXBsZV9JbmZvL3NhbXBsZXNfUGFjdXRhLmFubm90YXRpb25zLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICJcdCIsIGZpbGVFbmNvZGluZz0iVVRGLTgtQk9NIikgI3JlYWQgaW4gZmlsZQp0b3AzZ3JvdXBzIDwtIGMoIkdyb3VwMiIsICJHcm91cDMiLCAiR3JvdXA2IikKdHJlYXRtZW50aW5mbyA8LSBmaWx0ZXIodHJlYXRtZW50aW5mbywgZ3JvdXAlaW4ldG9wM2dyb3VwcykKdGFibGUodHJlYXRtZW50aW5mbyRncm91cCkKYGBgCgpMb2FkIHRoZSBpbnB1dCBmaWxlIGNvbnRhaW5pbmcgdGhlIGdlbmUgY291bnQgbWF0cml4CmBgYHtyfQojZ2VuZSBjb3VudCBtYXRyaXgKZ2NvdW50IDwtIGFzLmRhdGEuZnJhbWUocmVhZF9kZWxpbSgiR2Vub21lX0luZm8vUG9jaWxsb3BvcmFfYWN1dGFfS0JISXYyLmdlbnRyb21lLmZhLmd6LnNhbG1vbi5udW1yZWFkcy5tYXRyaXgiLCBkZWxpbSA9ICJcdCIsIGNvbF9uYW1lcyA9IFRSVUUsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpLCBmaWxlRW5jb2Rpbmc9IlVURi04LUJPTSIpICNyZWFkIGluIGZpbGUKcm93bmFtZXMoZ2NvdW50KSA8LSBnY291bnQkTmFtZSAjbWFrZXMgIk5hbWUiIHRoZSByb3duYW1lCmdjb3VudCA8LSBnY291bnRbLC1jKDEpXSAjZHJvcHMgdGhlICJOYW1lIiBjb2x1bW4KZ2NvdW50IDwtIHJvdW5kKGdjb3VudCkgI3JvdW5kIApkaW0oZ2NvdW50KTsgaGVhZChnY291bnQpWywxOjNdICN2aWV3IGRhdGFzZXQgYXR0cmlidXRlcwpnY291bnQgPC0gZ2NvdW50Wyx0cmVhdG1lbnRpbmZvJHNhbXBsZV0KYGBgCgpEZXRlcm1pbmUgbGlicmFyeSBzaXplCmBgYHtyfQpsaWJTaXplLmRmIDwtIGRhdGEuZnJhbWUobGliU2l6ZT1jb2xTdW1zKGdjb3VudCkpCmBgYAoKTWFrZSBER0Ugb2JqZWN0CmBgYHtyfQpER0VkYXQgPC0gREdFTGlzdChjb3VudHM9YXMubWF0cml4KGdjb3VudCksIHNhbXBsZXM9dHJlYXRtZW50aW5mbywKICAgICAgICAgICAgICAgICAgZ3JvdXA9dHJlYXRtZW50aW5mbyR0ZW1wKQpkaW0oREdFZGF0JGNvdW50cykKYGBgCgojIyAyLiBQcmUtZmlsdGVyaW5nCmBgYHtyfQpsaWIuc2l6ZXMuY3BtIDwtIGNvbFN1bXMoZ2NvdW50KS8xMDAwMDAwCmxpYi5zaXplcy5jcG0gPC0gdGliYmxlKHNhbXBsZT1jb2xuYW1lcyhnY291bnQpLCBsaWIuc2l6ZT1saWIuc2l6ZXMuY3BtKQoKa2VlcCA8LSByb3dTdW1zKGNwbShnY291bnQpID4gMy4zMykgPj0gMgp0YWJsZShrZWVwKQpER0VkYXQgPC0gREdFZGF0W2tlZXAsICwga2VlcC5saWIuc2l6ZXM9RkFMU0VdCmBgYAoKIyMgIDMuIERhdGEgbm9ybWFsaXphdGlvbiAgCmBgYHtyfQpER0VkYXQgPC0gY2FsY05vcm1GYWN0b3JzKERHRWRhdCkKREdFZGF0JHNhbXBsZXMKYGBgCgojIyAgNC4gUGxvdCBnbG9iYWwgZ2VuZSBleHByZXNzaW9uICAKCkxvZyB0cmFuc2Zvcm0gdGhlIGNvdW50cyBtYXRyaXggZm9yIHRoZSBuZXh0IHBsb3RzCmBgYHtyfQpER0VkYXQuY3BtIDwtIERHRWRhdCAjbWFrZSBhIGNvcHkgdGhlIGVkZ2VSIGRhdGFzZXQKREdFZGF0LmNwbSRjb3VudHMgPC0gY3BtKERHRWRhdC5jcG0kY291bnRzLCBsb2c9VFJVRSwgcHJpb3IuY291bnQ9NSkgI2xvZyB0cmFuc2Zvcm0gdGhlIGNvcHkgZm9yIHRoZSBuZXh0IHBsb3RzCmBgYAoKUnVuIGEgcHJpbmNpcGxlIGNvb3JkaW5hdGVzIGFuYWx5c2lzLCBhbGwgc2FtcGxlcwpgYGB7cn0KZCA8LSBkYXRhLmZyYW1lKERHRWRhdC5jcG0kc2FtcGxlcywgbmFtZSA9IGNvbG5hbWVzKERHRWRhdC5jcG0kY291bnRzKSwgVFBfdGVtcD1wYXN0ZShER0VkYXQuY3BtJHNhbXBsZXMkdGltZW5hbWUsIERHRWRhdC5jcG0kc2FtcGxlcyR0ZW1wLCBzZXA9Il8iKSkgI21ha2UgYSBkYXRhZnJhbWUgY29udGFpbmluZyBhbGwgcGxvdHRpbmcgaW5mbwojZCA8LSBmaWx0ZXIoZCwgdGVtcD09IkhvdCIpCmQkdGltZW5hbWUgPC0gZmFjdG9yKGQkdGltZW5hbWUsIGxldmVscyA9IGMoIjBfaG91ciIsICI2X2hvdXIiLCAiMTJfaG91ciIsICIzMF9ob3VyIiwgIjFfd2VlayIsICIyX3dlZWsiLCAiNF93ZWVrIiwgIjZfd2VlayIsICI4X3dlZWsiLCAiMTJfd2VlayIpKQpuY29sKERHRWRhdC5jcG0kY291bnRzWyxkJHNhbXBsZV0pCiMgUGFydGlhbCBMZWFzdCBTcXVhcmVzIEFuYWx5c2lzCm1peE9taWNfcGxzZGEgPC0gcGxzZGEodChER0VkYXQuY3BtJGNvdW50c1ssZCRzYW1wbGVdKSwgZCR0aW1lbmFtZSwgbmNvbXAgPSA4NSkKcGxvdFZhcihtaXhPbWljX3Bsc2RhLCBwbG90ID0gRikKcGxzZGFfcGxvdCA8LSBiaXBsb3QobWl4T21pY19wbHNkYSwgdmFyLmF4ZXMgPSBUUlVFLCBjdXRvZmYgPSAuOCwgaW5kLm5hbWVzID0gRik7IHBsc2RhX3Bsb3QKcGxvdEluZGl2KG1peE9taWNfcGxzZGEsIGluZC5uYW1lcyA9IEYsIGVsbGlwc2UgPSBUUlVFLCBsZWdlbmQgPSBUUlVFKQpgYGAKClJ1biBhIHByaW5jaXBsZSBjb29yZGluYXRlcyBhbmFseXNpcywgSG90IHNhbXBsZXMKYGBge3J9CmQgPC0gZGF0YS5mcmFtZShER0VkYXQuY3BtJHNhbXBsZXMsIG5hbWUgPSBjb2xuYW1lcyhER0VkYXQuY3BtJGNvdW50cyksIFRQX3RlbXA9cGFzdGUoREdFZGF0LmNwbSRzYW1wbGVzJHRpbWVuYW1lLCBER0VkYXQuY3BtJHNhbXBsZXMkdGVtcCwgc2VwPSJfIikpICNtYWtlIGEgZGF0YWZyYW1lIGNvbnRhaW5pbmcgYWxsIHBsb3R0aW5nIGluZm8KZCR0aW1lbmFtZSA8LSBmYWN0b3IoZCR0aW1lbmFtZSwgbGV2ZWxzID0gYygiMF9ob3VyIiwgIjZfaG91ciIsICIxMl9ob3VyIiwgIjMwX2hvdXIiLCAiMV93ZWVrIiwgIjJfd2VlayIsICI0X3dlZWsiLCAiNl93ZWVrIiwgIjhfd2VlayIsICIxMl93ZWVrIikpCmQgPC0gZmlsdGVyKGQsIHRlbXA9PSJIb3QiKQpuY29sKERHRWRhdC5jcG0kY291bnRzWyxkJHNhbXBsZV0pCiMgUGFydGlhbCBMZWFzdCBTcXVhcmVzIEFuYWx5c2lzCm1peE9taWNfcGxzZGEgPC0gcGxzZGEodChER0VkYXQuY3BtJGNvdW50c1ssZCRzYW1wbGVdKSwgZCRUUF90ZW1wLCBuY29tcCA9IDQ0KQpwbG90VmFyKG1peE9taWNfcGxzZGEsIHBsb3QgPSBGKQpwbHNkYV9wbG90IDwtIGJpcGxvdChtaXhPbWljX3Bsc2RhLCB2YXIuYXhlcyA9IFRSVUUsIGN1dG9mZiA9IC44LCBpbmQubmFtZXMgPSBGKTsgcGxzZGFfcGxvdApwbG90SW5kaXYobWl4T21pY19wbHNkYSwgaW5kLm5hbWVzID0gRiwgZWxsaXBzZSA9IFRSVUUsIGxlZ2VuZCA9IFRSVUUpCmBgYAoKUnVuIGEgcHJpbmNpcGxlIGNvb3JkaW5hdGVzIGFuYWx5c2lzLCBBbWIgc2FtcGxlcwpgYGB7cn0KZCA8LSBkYXRhLmZyYW1lKERHRWRhdC5jcG0kc2FtcGxlcywgbmFtZSA9IGNvbG5hbWVzKERHRWRhdC5jcG0kY291bnRzKSwgVFBfdGVtcD1wYXN0ZShER0VkYXQuY3BtJHNhbXBsZXMkdGltZW5hbWUsIERHRWRhdC5jcG0kc2FtcGxlcyR0ZW1wLCBzZXA9Il8iKSkgI21ha2UgYSBkYXRhZnJhbWUgY29udGFpbmluZyBhbGwgcGxvdHRpbmcgaW5mbwpkJHRpbWVuYW1lIDwtIGZhY3RvcihkJHRpbWVuYW1lLCBsZXZlbHMgPSBjKCIwX2hvdXIiLCAiNl9ob3VyIiwgIjEyX2hvdXIiLCAiMzBfaG91ciIsICIxX3dlZWsiLCAiMl93ZWVrIiwgIjRfd2VlayIsICI2X3dlZWsiLCAiOF93ZWVrIiwgIjEyX3dlZWsiKSkKZCA8LSBmaWx0ZXIoZCwgdGVtcD09IkFtYiIpCm5jb2woREdFZGF0LmNwbSRjb3VudHNbLGQkc2FtcGxlXSkKIyBQYXJ0aWFsIExlYXN0IFNxdWFyZXMgQW5hbHlzaXMKbWl4T21pY19wbHNkYSA8LSBwbHNkYSh0KERHRWRhdC5jcG0kY291bnRzWyxkJHNhbXBsZV0pLCBkJFRQX3RlbXAsIG5jb21wID0gNDEpCnBsb3RWYXIobWl4T21pY19wbHNkYSwgcGxvdCA9IEYpCnBsc2RhX3Bsb3QgPC0gYmlwbG90KG1peE9taWNfcGxzZGEsIHZhci5heGVzID0gVFJVRSwgY3V0b2ZmID0gLjgsIGluZC5uYW1lcyA9IEYpOyBwbHNkYV9wbG90CnBsb3RJbmRpdihtaXhPbWljX3Bsc2RhLCBpbmQubmFtZXMgPSBGLCBlbGxpcHNlID0gVFJVRSwgbGVnZW5kID0gVFJVRSkKYGBgCgojIEVtbWEgc2NyaXB0CmBgYHtyfQojIHNldCB3b3JraW5nIGRpcmVjdG9yeSBhbmQgbG9hZCBuZWNlc3NhcnkgcGFja2FnZXMKCmxpYnJhcnkocmVzaGFwZTIpCiNsaWJyYXJ5KGdnYmlwbG90KQpsaWJyYXJ5KGJyb29tKSAgIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoInRpZHltb2RlbHMvYnJvb20iKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoZ2dwdWJyKQojbGlicmFyeShnZ2ZvcnRpZnkpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShncmlkRXh0cmEpCiNsaWJyYXJ5KGdnZm9yY2UpCiMgc2V0IHNlZWQKc2V0LnNlZWQoNTQzMjEpCmBgYAoKTG9hZCBkYXRhc2V0cwpgYGB7cn0KZCA8LSBkYXRhLmZyYW1lKERHRWRhdC5jcG0kc2FtcGxlcywgbmFtZSA9IGNvbG5hbWVzKERHRWRhdC5jcG0kY291bnRzKSwgVFBfdGVtcD1wYXN0ZShER0VkYXQuY3BtJHNhbXBsZXMkdGltZW5hbWUsIERHRWRhdC5jcG0kc2FtcGxlcyR0ZW1wLCBzZXA9Il8iKSkgI21ha2UgYSBkYXRhZnJhbWUgCmQkdGltZW5hbWUgPC0gZmFjdG9yKGQkdGltZW5hbWUsIGxldmVscyA9IGMoIjBfaG91ciIsICI2X2hvdXIiLCAiMTJfaG91ciIsICIzMF9ob3VyIiwgIjFfd2VlayIsICIyX3dlZWsiLCAiNF93ZWVrIiwgIjZfd2VlayIsICI4X3dlZWsiLCAiMTJfd2VlayIpKQpgYGAKCmBgYHtyfQojUENBCk1jYXAucGNhLm91dCA8LSBwcmNvbXAodChER0VkYXQuY3BtJGNvdW50c1ssZCRzYW1wbGVdKSkgIywgY2VudGVyPUZBTFNFLCBzY2FsZT1GQUxTRSkgI3J1biBQQ0EKTS5zdW1tYXJ5IDwtIHN1bW1hcnkoTWNhcC5wY2Eub3V0KTsgTS5zdW1tYXJ5ICN2aWV3IHJlc3VsdHMKYmlwbG90KE1jYXAucGNhLm91dCkgI3Bsb3QgcmVzdWx0cwpgYGAKCmBgYHtyfQpNY2FwLnBjYS5vdXQgJT4lCiAgYXVnbWVudChkKSAlPiUgIyBhZGQgb3JpZ2luYWwgZGF0YXNldCBiYWNrIGluCiAgZ2dwbG90KGFlcyguZml0dGVkUEMxLCAuZml0dGVkUEM3LCBjb2xvciA9IGdyb3VwLjEpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGNvbG9yPSdibGFjaycsIGFlcyhzaGFwZT10ZW1wLCBmaWxsPWdyb3VwLjEpKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKGd1aWRlPSJsZWdlbmQiLCB2YWx1ZXM9YygnQW1iJz0yMSwgJ0hvdCc9MjQpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwoZ3VpZGU9ImxlZ2VuZCIsIHZhbHVlcz1jKCdHcm91cDInPSIjRkZCRDVDIiwgJ0dyb3VwMyc9IiNCODczRkYiIywgJ0dyb3VwNic9IiM0RUI5MDAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpICsKICAjeGxhYihwYXN0ZTAoIlBDMTogIiwgcm91bmQocGVyY2VudFZhclsxXSAqIDEwMCksICIlIHZhcmlhbmNlIikpICsKICAjeWxhYihwYXN0ZTAoIlBDNzogIiwgcm91bmQocGVyY2VudFZhcls3XSAqIDEwMCksICIlIHZhcmlhbmNlIikpICsKICBjb29yZF9maXhlZCgpICsKICB0aGVtZV9idygpICsgI1NldCBiYWNrZ3JvdW5kIGNvbG9yCiAgc3RhdF9lbGxpcHNlKCkgKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgIyBTZXQgYm9yZGVyCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgI1NldCBtYWpvciBncmlkbGluZXMKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAjU2V0IG1pbm9yIGdyaWRsaW5lcwogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMC42KSwgI1NldCBheGVzIGNvbG9yCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgI1NldCB0aGUgcGxvdCBiYWNrZ3JvdW5kCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArICNBeGlzIHRpdGxlIHNpemV0CiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaGFwZT0yMSkpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMS41LCBhbHBoYT0wLjUpICsKICB0aGVtZV9oYWxmX29wZW4oMTIpICsgYmFja2dyb3VuZF9ncmlkKCkrCiAgc3RhdF9lbGxpcHNlKCkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgI2dndGl0bGUoIk1vbnRpcG9yYSBjYXBpdGF0YSIpICsgCiAgI2ZhY2V0X2dyaWQoY29scz12YXJzKHRpbWVuYW1lKSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICdib2xkLml0YWxpYycsIHNpemUgPSAxNCwgaGp1c3QgPSAwKSkgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBmYWNlPSJib2xkIiksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZGVlcHNreWJsdWUiLCAiZmlyZWJyaWNrMSIpLCBhZXN0aGV0aWNzID0gYygiY29sb3VyIikpICsKICB4bGFiKCJQQzEgMjQlIikgKyB5bGFiKCJQQzcgMiUiKQoKTWNhcC5wY2Eub3V0ICU+JQogIGF1Z21lbnQoZCkgJT4lICMgYWRkIG9yaWdpbmFsIGRhdGFzZXQgYmFjayBpbgogIGdncGxvdChhZXMoLmZpdHRlZFBDNSwgLmZpdHRlZFBDNiwgY29sb3IgPSB0ZW1wKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAxLjUsIGFscGhhPTAuNSkgKwogIHRoZW1lX2hhbGZfb3BlbigxMikgKyBiYWNrZ3JvdW5kX2dyaWQoKSsKICBzdGF0X2VsbGlwc2UoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICAjZ2d0aXRsZSgiTW9udGlwb3JhIGNhcGl0YXRhIikgKyAKICBmYWNldF9ncmlkKGNvbHM9dmFycyh0aW1lbmFtZSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAnYm9sZC5pdGFsaWMnLCBzaXplID0gMTQsIGhqdXN0ID0gMCkpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiwgZmFjZT0iYm9sZCIpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAjc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImRlZXBza3libHVlIiwgImZpcmVicmljazEiKSwgYWVzdGhldGljcyA9IGMoImNvbG91ciIpKSArCiAgeGxhYigiUEM1IDIzLjc2JSIpICsgeWxhYigiUEM2IDE2LjA5JSIpCmBgYAoKYGBge3J9Ck1jYXBpdGF0YS5hbGwgPC0gTWNhcC5wY2Eub3V0ICU+JQogIGF1Z21lbnQoZCkgJT4lICMgYWRkIG9yaWdpbmFsIGRhdGFzZXQgYmFjayBpbgogIGdyb3VwX2J5KHRpbWVuYW1lLCB0ZW1wKSAlPiUKICBtdXRhdGUoUEM1Lm1lYW4gPSBtZWFuKC5maXR0ZWRQQzUpLAogICAgICAgICBQQzYubWVhbiA9IG1lYW4oLmZpdHRlZFBDNikpCgptY2FwLkhvdC5zZWdtZW50cyA8LSBNY2FwaXRhdGEuYWxsICU+JSBzdWJzZXQodGVtcCA9PSAiSG90IikgJT4lCiAgc2VsZWN0KHRpbWVuYW1lLCB0ZW1wLCBQQzUubWVhbiwgUEM2Lm1lYW4pICU+JQogIGdhdGhlcih2YXJpYWJsZSwgdmFsdWUsIC0odGltZW5hbWU6dGVtcCkpICU+JQogIHVuaXRlKGdyb3VwLCB0aW1lbmFtZSwgdmFyaWFibGUpICU+JSBkaXN0aW5jdCgpICU+JQogIHNwcmVhZChncm91cCwgdmFsdWUpCgptY2FwLmFtYi5zZWdtZW50cyA8LSBNY2FwaXRhdGEuYWxsICU+JSBzdWJzZXQodGVtcCA9PSAiQW1iIikgJT4lCiAgc2VsZWN0KHRpbWVuYW1lLCB0ZW1wLCBQQzUubWVhbiwgUEM2Lm1lYW4pICU+JQogIGdhdGhlcih2YXJpYWJsZSwgdmFsdWUsIC0odGltZW5hbWU6dGVtcCkpICU+JQogIHVuaXRlKGdyb3VwLCB0aW1lbmFtZSwgdmFyaWFibGUpICU+JSBkaXN0aW5jdCgpICU+JQogIHNwcmVhZChncm91cCwgdmFsdWUpCmBgYAoKYGBge3J9Ck1jYXBpdGF0YS5hbGwuZmlnIDwtIGdncGxvdChNY2FwaXRhdGEuYWxsLCBhZXMoLmZpdHRlZFBDNSwgLmZpdHRlZFBDNiwgY29sb3IgPSBncm91cC4xKSkgKyAKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgMF9ob3VyX1BDNS5tZWFuYCwgeSA9IGAwX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDZfaG91cl9QQzUubWVhbmAsIHllbmQgPSBgNl9ob3VyX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLkhvdC5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDBfaG91ciB0byA2X2hvdXIgSG90CiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDZfaG91cl9QQzUubWVhbmAsIHkgPSBgNl9ob3VyX1BDNi5tZWFuYCwgeGVuZCA9IGAxMl9ob3VyX1BDNS5tZWFuYCwgeWVuZCA9IGAxMl9ob3VyX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLkhvdC5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDZfaG91ciB0byAxMl9ob3VyIEhvdAogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDEyX2hvdXJfUEM1Lm1lYW5gLCB5ID0gYDEyX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDMwX2hvdXJfUEM1Lm1lYW5gLCB5ZW5kID0gYDMwX2hvdXJfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuSG90LnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFKSArICMgMTJfaG91ciB0byAzMF9ob3VyIEhvdAogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDMwX2hvdXJfUEM1Lm1lYW5gLCB5ID0gYDMwX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDFfd2Vla19QQzUubWVhbmAsIHllbmQgPSBgMV93ZWVrX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLkhvdC5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDMwX2hvdXIgdG8gMV93ZWVrIEhvdAogICAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgMV93ZWVrX1BDNS5tZWFuYCwgeSA9IGAxX3dlZWtfUEM2Lm1lYW5gLCB4ZW5kID0gYDJfd2Vla19QQzUubWVhbmAsIHllbmQgPSBgMl93ZWVrX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLkhvdC5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDFfd2VlayB0byAyX3dlZWsgSG90CiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDJfd2Vla19QQzUubWVhbmAsIHkgPSBgMl93ZWVrX1BDNi5tZWFuYCwgeGVuZCA9IGA0X3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDRfd2Vla19QQzYubWVhbmAsIGNvbG91ciA9IHRlbXApLCBkYXRhID0gbWNhcC5Ib3Quc2VnbWVudHMsIHNpemU9MSwgc2hvdy5sZWdlbmQ9RkFMU0UpICsgIyAyX3dlZWsgdG8gNF93ZWVrIEhvdAogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDRfd2Vla19QQzUubWVhbmAsIHkgPSBgNF93ZWVrX1BDNi5tZWFuYCwgeGVuZCA9IGA2X3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDZfd2Vla19QQzYubWVhbmAsIGNvbG91ciA9IHRlbXApLCBkYXRhID0gbWNhcC5Ib3Quc2VnbWVudHMsIHNpemU9MSwgc2hvdy5sZWdlbmQ9RkFMU0UpICsgIyA0X3dlZWsgdG8gOF93ZWVrIEhvdAogIGdlb21fc2VnbWVudChhZXMoeCA9IGA2X3dlZWtfUEM1Lm1lYW5gLCB5ID0gYDZfd2Vla19QQzYubWVhbmAsIHhlbmQgPSBgOF93ZWVrX1BDNS5tZWFuYCwgeWVuZCA9IGA4X3dlZWtfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuSG90LnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFKSArICMgNF93ZWVrIHRvIDhfd2VlayBIb3QKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgOF93ZWVrX1BDNS5tZWFuYCwgeSA9IGA4X3dlZWtfUEM2Lm1lYW5gLCB4ZW5kID0gYDEyX3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDEyX3dlZWtfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuSG90LnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFLCBhcnJvdyA9IGFycm93KCkpICsgIyA4X3dlZWsgdG8gMTJfd2VlayBIb3QKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgMF9ob3VyX1BDNS5tZWFuYCwgeSA9IGAwX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDZfaG91cl9QQzUubWVhbmAsIHllbmQgPSBgNl9ob3VyX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLmFtYi5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDBfaG91ciB0byA2X2hvdXIgYW1iCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDZfaG91cl9QQzUubWVhbmAsIHkgPSBgNl9ob3VyX1BDNi5tZWFuYCwgeGVuZCA9IGAxMl9ob3VyX1BDNS5tZWFuYCwgeWVuZCA9IGAxMl9ob3VyX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLmFtYi5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDZfaG91ciB0byAxMl9ob3VyIGFtYgogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDEyX2hvdXJfUEM1Lm1lYW5gLCB5ID0gYDEyX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDMwX2hvdXJfUEM1Lm1lYW5gLCB5ZW5kID0gYDMwX2hvdXJfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuYW1iLnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFKSArICMgMTJfaG91ciB0byAzMF9ob3VyIGFtYgogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDMwX2hvdXJfUEM1Lm1lYW5gLCB5ID0gYDMwX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDFfd2Vla19QQzUubWVhbmAsIHllbmQgPSBgMV93ZWVrX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLmFtYi5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDMwX2hvdXIgdG8gMV93ZWVrIGFtYgogICAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgMV93ZWVrX1BDNS5tZWFuYCwgeSA9IGAxX3dlZWtfUEM2Lm1lYW5gLCB4ZW5kID0gYDJfd2Vla19QQzUubWVhbmAsIHllbmQgPSBgMl93ZWVrX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLmFtYi5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDFfd2VlayB0byAyX3dlZWsgYW1iCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDJfd2Vla19QQzUubWVhbmAsIHkgPSBgMl93ZWVrX1BDNi5tZWFuYCwgeGVuZCA9IGA0X3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDRfd2Vla19QQzYubWVhbmAsIGNvbG91ciA9IHRlbXApLCBkYXRhID0gbWNhcC5hbWIuc2VnbWVudHMsIHNpemU9MSwgc2hvdy5sZWdlbmQ9RkFMU0UpICsgIyAyX3dlZWsgdG8gNF93ZWVrIEFNQgogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDRfd2Vla19QQzUubWVhbmAsIHkgPSBgNF93ZWVrX1BDNi5tZWFuYCwgeGVuZCA9IGA2X3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDZfd2Vla19QQzYubWVhbmAsIGNvbG91ciA9IHRlbXApLCBkYXRhID0gbWNhcC5hbWIuc2VnbWVudHMsIHNpemU9MSwgc2hvdy5sZWdlbmQ9RkFMU0UpICsgIyA0X3dlZWsgdG8gOF93ZWVrIGFtYgogIGdlb21fc2VnbWVudChhZXMoeCA9IGA2X3dlZWtfUEM1Lm1lYW5gLCB5ID0gYDZfd2Vla19QQzYubWVhbmAsIHhlbmQgPSBgOF93ZWVrX1BDNS5tZWFuYCwgeWVuZCA9IGA4X3dlZWtfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuYW1iLnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFKSArICMgNF93ZWVrIHRvIDhfd2VlayBhbWIKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgOF93ZWVrX1BDNS5tZWFuYCwgeSA9IGA4X3dlZWtfUEM2Lm1lYW5gLCB4ZW5kID0gYDEyX3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDEyX3dlZWtfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuYW1iLnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFLCBhcnJvdyA9IGFycm93KCkpICsgIyA4X3dlZWsgdG8gMTJfd2VlayBBTUIKICBnZW9tX3BvaW50KHNpemUgPSAxLjUsIGFscGhhPTAuMykgKwogIGdlb21fcG9pbnQoYWVzKHg9UEM1Lm1lYW4sIHk9UEM2Lm1lYW4pLCBjb2xvcj0iZGFya2dyZXkiKSArCiAgZ2VvbV90ZXh0KHNpemUgPSAyLCBhZXMoUEM1Lm1lYW4sIFBDNi5tZWFuLCBsYWJlbD10aW1lbmFtZSksIHZqdXN0PS0xLjUsIGNvbG9yPSJibGFjayIpICsKICB0aGVtZV9oYWxmX29wZW4oMTIpICsgYmFja2dyb3VuZF9ncmlkKCkgKwogICNnZ3RpdGxlKCJNb250aXBvcmEgY2FwaXRhdGEiKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44LCAwLjkpKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gJ2JvbGQuaXRhbGljJywgc2l6ZSA9IDE0LCBoanVzdCA9IDApKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIsIGZhY2U9ImJvbGQiKSkgKwogICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZGVlcHNreWJsdWUiLCAiZmlyZWJyaWNrMSIpLCBhZXN0aGV0aWNzID0gYygiY29sb3VyIikpICsKICB4bGFiKCJQQzUgMjMuNzYlIikgKyB5bGFiKCJQQzYgMTYuMDklIik7IE1jYXBpdGF0YS5hbGwuZmlnCk1jYXBpdGF0YS5hbGwuZmlnIApnZ3NhdmUoIk91dHB1dC8xYy1QYWN1LWVkZ2VSLWFsbHNhbXBsZXMtUENBLXRpbWVuYW1lLWFycm93cy5wZGYiLCBNY2FwaXRhdGEuYWxsLmZpZywgd2lkdGggPSA2LCBoZWlnaHQgPSA1LCB1bml0cyA9IGMoImluIikpCmBgYA==